package metrictransformer

import (
	"regexp"

	ms "gitee.com/shipnet/flogo_metric_store"
	"github.com/project-flogo/core/data"

	"github.com/project-flogo/core/data/mapper"
	"github.com/project-flogo/core/data/resolve"

	"github.com/project-flogo/core/data/coerce"
)

type Filter interface {
	Apply(metric ms.MetricData) bool
}

type plainFilter struct {
	value string
}

func NewPlainFilter(params interface{}) (Filter, error) {
	p, err := coerce.ToString(params)
	if err != nil {
		return nil, err
	}
	pf := plainFilter{
		value: p,
	}
	return &pf, nil
}

func (p *plainFilter) Apply(metric ms.MetricData) bool {
	return p.value == metric.ID
}

type regexpFilter struct {
	re *regexp.Regexp
}

func NewRegexpFilter(params interface{}) (Filter, error) {
	p, err := coerce.ToString(params)
	if err != nil {
		return nil, err
	}
	re, err := regexp.Compile(p)
	if err != nil {
		return nil, err
	}
	rf := regexpFilter{
		re: re,
	}
	return &rf, nil
}

func (p *regexpFilter) Apply(metric ms.MetricData) bool {
	return p.re.MatchString(metric.ID)
}

type exprFilter struct {
	key string
	m   mapper.Mapper
}

func NewExprFilter(params interface{}) (Filter, error) {
	expr, err := coerce.ToString(params)
	if err != nil {
		return nil, err
	}
	f := mapper.NewFactory(resolve.GetBasicResolver())
	mappings := map[string]interface{}{
		"key": expr,
	}
	mapper, err := f.NewMapper(mappings)
	if err != nil {
		return nil, err
	}
	ef := exprFilter{
		key: "key",
		m:   mapper,
	}
	return &ef, nil
}

func (p *exprFilter) Apply(metric ms.MetricData) bool {
	values := toMap(metric)
	scope := data.NewSimpleScope(values, nil)
	results, err := p.m.Apply(scope)
	if err != nil {
		return false
	}
	b, _ := coerce.ToBool(results[p.key])
	return b
}
